Fixes #2655.
#[derive(RustcEncodable, RustcDecodable, Clone, PartialEq, Eq, Debug, Hash)]
pub struct Profile {
- pub opt_level: u32,
+ pub opt_level: String,
pub lto: bool,
pub codegen_units: Option<u32>, // None = use rustc default
pub rustc_args: Option<Vec<String>>,
pub fn default_release() -> Profile {
Profile {
- opt_level: 3,
+ opt_level: "3".to_string(),
debuginfo: false,
..Profile::default()
}
impl Default for Profile {
fn default() -> Profile {
Profile {
- opt_level: 0,
+ opt_level: "0".to_string(),
lto: false,
codegen_units: None,
rustc_args: None,
Kind::Target => cx.target_triple(),
})
.env("DEBUG", &profile.debuginfo.to_string())
- .env("OPT_LEVEL", &profile.opt_level.to_string())
+ .env("OPT_LEVEL", &profile.opt_level)
.env("PROFILE", if cx.build_config.release {"release"} else {"debug"})
.env("HOST", cx.host_triple())
.env("RUSTC", &try!(cx.config.rustc()).path)
let build_type = if self.is_release { "release" } else { "debug" };
let profile = cx.lib_profile(cx.resolve.root());
- let mut opt_type = String::from(if profile.opt_level > 0 { "optimized" }
- else { "unoptimized" });
+ let mut opt_type = String::from(if profile.opt_level == "0" { "unoptimized" }
+ else { "optimized" });
if profile.debuginfo {
opt_type = opt_type + " + debuginfo";
}
unit: &Unit,
crate_types: &[&str]) {
let Profile {
- opt_level, lto, codegen_units, ref rustc_args, debuginfo,
+ ref opt_level, lto, codegen_units, ref rustc_args, debuginfo,
debug_assertions, rpath, test, doc: _doc, run_custom_build,
ref panic, rustdoc_args: _,
} = *unit.profile;
cmd.arg("-C").arg("prefer-dynamic");
}
- if opt_level != 0 {
+ if opt_level != "0" {
cmd.arg("-C").arg(&format!("opt-level={}", opt_level));
}
cmd.args(args);
}
- if debug_assertions && opt_level > 0 {
+ if debug_assertions && opt_level != "0" {
cmd.args(&["-C", "debug-assertions=on"]);
- } else if !debug_assertions && opt_level == 0 {
+ } else if !debug_assertions && opt_level == "0" {
cmd.args(&["-C", "debug-assertions=off"]);
}
release: Option<TomlProfile>,
}
+#[derive(Clone)]
+pub struct TomlOptLevel(String);
+
+impl Decodable for TomlOptLevel {
+ fn decode<D: Decoder>(d: &mut D) -> Result<TomlOptLevel, D::Error> {
+ match d.read_u32() {
+ Ok(i) => Ok(TomlOptLevel(i.to_string())),
+ Err(_) => {
+ match d.read_str() {
+ Ok(ref s) if s == "s" || s == "z" =>
+ Ok(TomlOptLevel(s.to_string())),
+ Ok(_) | Err(_) =>
+ Err(d.error("expected an integer, a string \"z\" or a string \"s\""))
+ }
+ }
+ }
+ }
+}
+
#[derive(RustcDecodable, Clone, Default)]
pub struct TomlProfile {
- opt_level: Option<u32>,
+ opt_level: Option<TomlOptLevel>,
lto: Option<bool>,
codegen_units: Option<u32>,
debug: Option<bool>,
fn merge(profile: Profile, toml: Option<&TomlProfile>) -> Profile {
let &TomlProfile {
- opt_level, lto, codegen_units, debug, debug_assertions, rpath,
+ ref opt_level, lto, codegen_units, debug, debug_assertions, rpath,
ref panic
} = match toml {
Some(toml) => toml,
None => return profile,
};
Profile {
- opt_level: opt_level.unwrap_or(profile.opt_level),
+ opt_level: opt_level.clone().unwrap_or(TomlOptLevel(profile.opt_level)).0,
lto: lto.unwrap_or(profile.lto),
codegen_units: codegen_units,
rustc_args: None,
use std::env;
use std::path::MAIN_SEPARATOR as SEP;
+use cargotest::is_nightly;
use cargotest::support::{project, execs};
use hamcrest::assert_that;
)));
}
+#[test]
+fn opt_level_override_0() {
+ let mut p = project("foo");
+ p = p
+ .file("Cargo.toml", r#"
+ [package]
+
+ name = "test"
+ version = "0.0.0"
+ authors = []
+
+ [profile.dev]
+ opt-level = 0
+ "#)
+ .file("src/lib.rs", "");
+ assert_that(p.cargo_process("build").arg("-v"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] test v0.0.0 ({url})
+[RUNNING] `rustc src{sep}lib.rs --crate-name test --crate-type lib \
+ -g \
+ -C metadata=[..] \
+ --out-dir [..] \
+ --emit=dep-info,link \
+ -L dependency={dir}{sep}target{sep}debug{sep}deps`
+[FINISHED] [..] target(s) in [..]
+", sep = SEP,
+dir = p.root().display(),
+url = p.url()
+)));
+}
+
+fn check_opt_level_override(profile_level: &str, rustc_level: &str) {
+ let mut p = project("foo");
+ p = p
+ .file("Cargo.toml", &format!(r#"
+ [package]
+
+ name = "test"
+ version = "0.0.0"
+ authors = []
+
+ [profile.dev]
+ opt-level = {level}
+ "#, level = profile_level))
+ .file("src/lib.rs", "");
+ assert_that(p.cargo_process("build").arg("-v"),
+ execs().with_status(0).with_stderr(&format!("\
+[COMPILING] test v0.0.0 ({url})
+[RUNNING] `rustc src{sep}lib.rs --crate-name test --crate-type lib \
+ -C opt-level={level} \
+ -g \
+ -C debug-assertions=on \
+ -C metadata=[..] \
+ --out-dir [..] \
+ --emit=dep-info,link \
+ -L dependency={dir}{sep}target{sep}debug{sep}deps`
+[FINISHED] [..] target(s) in [..]
+", sep = SEP,
+dir = p.root().display(),
+url = p.url(),
+level = rustc_level
+)));
+}
+
+#[test]
+fn opt_level_overrides() {
+ if !is_nightly() { return }
+
+ for &(profile_level, rustc_level) in &[
+ ("1", "1"),
+ ("2", "2"),
+ ("3", "3"),
+ ("\"s\"", "s"),
+ ("\"z\"", "z"),
+ ] {
+ check_opt_level_override(profile_level, rustc_level)
+ }
+}
+
#[test]
fn top_level_overrides_deps() {
let mut p = project("foo");